package pl.agh.pp.zephyr.web;

import java.io.Serializable;
import java.text.DateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.NoneScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.icefaces.application.PortableRenderer;
import org.icefaces.application.PushRenderer;

@ManagedBean(name = "pushLogger")
@NoneScoped
public class PushLogger extends Handler implements Serializable {

	private static final long serialVersionUID = 1L;

	public static final String APPLICATION_PUSH_GROUP = "all";

	private static Logger log = Logger.getLogger(PushLogger.class
			.getSimpleName());

	private final List<Message> messages = new LinkedList<Message>();

	private boolean on = true, rich, changed = true;

	private final long interval = 1000L;
	private final Timer clockTimer;
	private final TimerTask renderTask;

	private final PortableRenderer pr;

	public PushLogger() {
		log.setLevel(Level.ALL);
		PushRenderer.addCurrentSession(APPLICATION_PUSH_GROUP);
		pr = PushRenderer
				.getPortableRenderer(FacesContext.getCurrentInstance());

		clockTimer = new Timer(true);
		renderTask = new TimerTask() {

			public void run() {
				if (on && changed) {
					pr.render(APPLICATION_PUSH_GROUP);
				}

				changed = false;
			}
		};
		clockTimer.schedule(renderTask, 0, interval);
	}

	@PreDestroy
	public void destroy() {
		renderTask.cancel();
		clockTimer.cancel();
	}

	public List<Message> getMessages() {
		return messages;
	}

	public void reset(ActionEvent a) {
		messages.clear();
	}

	public void startStop(ActionEvent a) {
		on = !on;
	}

	public void log(String from, String mesg) {
		messages.add(new Message(from, mesg));
	}

	public void log(String mesg) {
		this.log("Anonymous", mesg);
	}

	public Boolean getOn() {
		return on;
	}

	public Boolean getRich() {
		return rich;
	}

	public void setRich(Boolean rich) {
		this.rich = rich;
	}

	public static class Message {
		public final String sender, content, date = DateFormat
				.getDateInstance().format(new Date());

		public Message(String sender, String content) {
			super();
			this.sender = sender;
			// zrobienie miejsca, żeby się lepiej wyświetlało
			this.content = content.replaceAll(",(?=\\S)", ", ").replace("\n", "<br/>");
		}

		public String getSender() {
			return sender;
		}

		public String getContent() {
			return content;
		}

		public String getDate() {
			return date;
		}
	}

	@Override
	public void publish(LogRecord record) {
		messages.add(new Message(record.getLoggerName(), record.getMessage()
				.replace("|", " | ")));
		changed = true;
	}

	@Override
	public void flush() {
	}

	@Override
	public void close() throws SecurityException {
	}

	public void richToggle(ActionEvent a) {
		rich = !rich;
	}

}
